﻿/**************************************************************
 *
 * 唯一标识：282515fb-b06b-46fb-ad87-5090e4a04b5e
 * 命名空间：Sgr.Identity
 * 创建时间：2023/8/21 20:26:12
 * 机器名称：DESKTOP-S0D075D
 * 创建者：antho
 * 电子邮箱：fengqinhua2016@163.com
 * 描述：
 *
 **************************************************************/

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;

namespace Sgr.Identity
{
    public class HttpCookieOptions
    {
        /// <summary>
        /// 设置存储用户登录信息的Cookie名称
        /// </summary>
        public string Name { get; set; } = string.Empty;

        /// <summary>
        /// 设置存储用户登录信息（用户Token信息）的Cookie，无法通过客户端浏览器脚本(如JavaScript等)访问到
        /// </summary>
        public bool HttpOnly { get; set; } = true;

        /// <summary>
        /// 过期时间(秒),默认1个小时
        /// </summary>
        public int ExpireSeconds { get; set; } = 3600;

        /// <summary>
        /// 是否在过期时间过半的时候，自动延期
        /// </summary>
        public bool SlidingExpiration { get; set; } = true;

        /// <summary>
        /// 登录地址。认证失败，会自动跳转到这个地址
        /// </summary>
        public string LoginPath { get; set; } = string.Empty;

        /// <summary>
        /// 注销路径，指向一个Action
        /// </summary>
        public string LogoutPath { get; set; } = string.Empty;

        /// <summary>
        /// 访问拒绝页路径，指向一个Action
        /// </summary>
        public string AccessDeniedPath { get; set; } = string.Empty;

        /// <summary>
        /// ReturnUrlParameter
        /// </summary>
        public string ReturnUrlParameter { get; set; } = string.Empty;

        /// <summary>
        /// 指定Cookie在跨站请求中的发送行为，这有助于减少跨站请求伪造（CSRF）等安全威胁
        /// <para>None: 无论请求是否来自同一站点，都会发送Cookie。这可能会增加安全风险，但在某些情况下是必要的，例如，当第三方网站需要读取Cookie时</para>
        /// <para>Lax: 默认情况下，Cookie会随同站点的请求一起发送。但是，如果请求是通过链接（如a标签）导航到的，即使该请求来自另一个站点，Cookie也会一起发送。这种设置可以在不影响用户体验的前提下提供一定的安全保护</para>
        /// <para>Strict: 只有在请求来自同一站点时才发送Cookie。这是为了防止CSRF攻击，但也可能影响第三方网站的功能</para>
        /// </summary>
        public string SameSite { get; set; } = "None";

        /// <summary>
        /// 指定Cookie在不同安全环境下的行为
        /// <para>None: 不应用任何安全策略，Cookie可以在非安全连接（HTTP）上发送</para>
        /// <para>SameSiteAlways‌: Cookie仅在同站点的请求中发送，无论是否在安全连接上</para>
        /// <para>Always‌: Cookie仅在安全连接（HTTPS）上发送，不在非安全连接（HTTP）上发送</para>
        /// </summary>
        public string SecurePolicy { get; set; } = "None";

        /// <summary>
        /// 创建缺省配置项
        /// </summary>
        /// <returns></returns>
        public static HttpCookieOptions CreateDefault()
        {
            return new HttpCookieOptions()
            {
                Name = "sgrCookie",
                HttpOnly = true,
                ExpireSeconds = 3600,
                SlidingExpiration = true,
                LoginPath = "/",
                SameSite = "None",
                SecurePolicy = "None"
            };
        }

        public static CookieSecurePolicy ToCookieSecurePolicy(string securePolicy)
        {
            CookieSecurePolicy policy = CookieSecurePolicy.None;
            switch (securePolicy)
            {
                case "None":
                    policy = CookieSecurePolicy.None;
                    break;

                case "SameAsRequest":
                    policy = CookieSecurePolicy.SameAsRequest;
                    break;

                case "Always":
                    policy = CookieSecurePolicy.Always;
                    break;

                default:
                    policy = CookieSecurePolicy.None;
                    break;
            }

            return policy;
        }

        public static SameSiteMode ToSameSiteMode(string sameSite)
        {
            SameSiteMode mode = SameSiteMode.None;
            switch (sameSite)
            {
                case "None":
                    mode = SameSiteMode.None;
                    break;

                case "Lax":
                    mode = SameSiteMode.Lax;
                    break;

                case "Strict":
                    mode = SameSiteMode.Strict;
                    break;

                default:
                    mode = SameSiteMode.None;
                    break;
            }
            return mode;
        }
    }
}